home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fsrmt / fsrmtDomain.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  63KB  |  1,828 lines

  1. /* 
  2.  * fsrmtDomain.c --
  3.  *
  4.  *    This has the stubs for remote naming operations in a Sprite domain.
  5.  *    These routines are presented in pairs, the client stub followed
  6.  *    by the server stub.  The general style is for the server stub
  7.  *    to call the LocalDomain equivalent of the SpriteDomain client stub.
  8.  *    i.e. FsrmtOpen invokes via RPC Fsrmt_RpcOpen which calls
  9.  *    FslclOpen.  Occasionally a client or server stub will do some
  10.  *    extra processing, or use lower level primatives for efficiency.
  11.  *
  12.  * Copyright (C) 1987 Regents of the University of California
  13.  * All rights reserved.
  14.  * Permission to use, copy, modify, and distribute this
  15.  * software and its documentation for any purpose and without
  16.  * fee is hereby granted, provided that the above copyright
  17.  * notice appear in all copies.  The University of California
  18.  * makes no representations about the suitability of this
  19.  * software for any purpose.  It is provided "as is" without
  20.  * express or implied warranty.
  21.  */
  22.  
  23. #ifndef lint
  24. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fsrmt/fsrmtDomain.c,v 9.15 92/12/13 18:16:58 mgbaker Exp $ SPRITE (Berkeley)";
  25. #endif not lint
  26.  
  27. #include <sprite.h>
  28. #include <fs.h>
  29. #include <fsconsist.h>
  30. #include <fsio.h>
  31. #include <fsutil.h>
  32. #include <fsNameOps.h>
  33. #include <fsrmtNameOpsInt.h>
  34. #include <fsprefix.h>
  35. #include <fsrmtInt.h>
  36. #include <fslcl.h>
  37. #include <fsStat.h>
  38. #include <recov.h>
  39. #include <proc.h>
  40. #include <rpc.h>
  41. #include <vm.h>
  42. #include <dbg.h>
  43.  
  44. #include <string.h>
  45. #include <rpcServer.h>
  46.  
  47. /*
  48.  * Used to contain fileID and stream data results from open calls.
  49.  */
  50. typedef    struct    FsPrefixReplyParam {
  51.     FsrmtUnionData    openData;
  52.     Fs_FileID    fileID;
  53. } FsPrefixReplyParam;
  54.  
  55. static ReturnStatus TwoNameOperation _ARGS_((int command, 
  56.     Fs_HandleHeader *prefixHandle1, char *relativeName1, 
  57.     Fs_HandleHeader *prefixHandle2, char *relativeName2, 
  58.     Fs_LookupArgs *lookupArgsPtr, Fs_RedirectInfo **newNameInfoPtrPtr, 
  59.     Boolean *name1ErrorPtr));
  60.  
  61. /*
  62.  *----------------------------------------------------------------------
  63.  *
  64.  * FsrmtImport --
  65.  *
  66.  *    Get a handle for a prefix.  This conducts an RPC_FS_PREFIX
  67.  *    to see if there is a server for the prefix.  If there is one this
  68.  *    routine installs a handle for it.  The pointer to the handle
  69.  *    is returned.
  70.  *
  71.  * Results:
  72.  *    FAILURE or RPC_TIMEOUT if we couldn't find a server for the prefix.
  73.  *    SUCCESS if we did find a server.  In this case the results are
  74.  *    a pointer to a handle for the prefix.
  75.  *
  76.  * Side effects:
  77.  *    State is left on the server machine about the open prefix.  The
  78.  *    responding file server is registered with the recovery module
  79.  *    so we find out when it goes away and when it reboots.
  80.  *    
  81.  *----------------------------------------------------------------------
  82.  */
  83. /*ARGSUSED*/
  84. ReturnStatus
  85. FsrmtImport(prefix, serverID, idPtr, domainTypePtr, hdrPtrPtr)
  86.     char    *prefix;        /* Prefix for which to find a server. */
  87.     int        serverID;        /* Suggested server ID.  This is the
  88.                      * broadcast address for nearby domains,
  89.                      * or a specific hostID, or a remote
  90.                      * network for remote broadcasting */
  91.     Fs_UserIDs    *idPtr;            /* IGNORED */
  92.     int        *domainTypePtr;        /* Return - FS_REMOTE_SPRITE_DOMAIN or
  93.                      *          FS_REMOTE_PSEUDO_DOMAIN */
  94.     Fs_HandleHeader **hdrPtrPtr;        /* Return - handle for prefix table */
  95. {
  96.     ReturnStatus     status;
  97.     Rpc_Storage     storage;
  98.     Fs_FileID        *fileIDPtr;    /* Returned from server */
  99.     ClientData        streamData;    /* Returned from server */
  100.     int            flags = FS_PREFIX;
  101.     FsPrefixReplyParam    prefixReplyParam;
  102.  
  103.     *hdrPtrPtr = (Fs_HandleHeader *)NIL;
  104.     *domainTypePtr = -1;
  105.  
  106.     storage.requestParamPtr = (Address) NIL;
  107.     storage.requestParamSize = 0;
  108.     storage.requestDataPtr = (Address)prefix;
  109.     storage.requestDataSize = strlen(prefix)+1;
  110.  
  111.     storage.replyParamPtr = (Address)&prefixReplyParam;
  112.     storage.replyParamSize = sizeof(FsPrefixReplyParam);
  113.     storage.replyDataPtr = (Address)NIL;
  114.     storage.replyDataSize = 0;
  115.     fileIDPtr = &(prefixReplyParam.fileID);
  116.  
  117.     status = Rpc_Call(serverID, RPC_FS_PREFIX, &storage);
  118.     /*
  119.      * It is necessary to allocate and copy over the stream data, since
  120.      * the ioOpen proc frees this space.
  121.      */
  122.     streamData = (ClientData)malloc(sizeof(FsrmtUnionData));
  123.     *((FsrmtUnionData *) streamData) = prefixReplyParam.openData;
  124.  
  125.     if (status == SUCCESS) {
  126.     /*
  127.      * Use the client-open routine to set up an I/O handle for the prefix.
  128.      */
  129.     status = (*fsio_StreamOpTable[fileIDPtr->type].ioOpen)(fileIDPtr, &flags,
  130.             rpc_SpriteID, (ClientData)streamData, prefix, hdrPtrPtr);
  131.     if (status == SUCCESS) {
  132.         /*
  133.          * Register the server with the recovery module so we find out
  134.          * when it goes away and when it reboots.
  135.          */
  136.         Recov_RebootRegister((*hdrPtrPtr)->fileID.serverID, Fsutil_Reopen,
  137.                  (ClientData)NIL);
  138.         *domainTypePtr = FS_REMOTE_SPRITE_DOMAIN;
  139.     }
  140.     }
  141.  
  142.     return(status);
  143. }
  144.  
  145. /*
  146.  *----------------------------------------------------------------------
  147.  *
  148.  * Fsrmt_RpcPrefix --
  149.  *
  150.  *    Server stub for RPC_FS_PREFIX.  This looks in the prefix
  151.  *    table for the given prefix.  If found, the handle is opened
  152.  *    for use by the client, and the resulting streamData is returned.
  153.  *
  154.  * Results:
  155.  *    If this procedure returns SUCCESS then a reply has been sent to
  156.  *    the client.  If the arguments are bad then an error is
  157.  *    returned and the main level sends back an error reply.
  158.  *
  159.  * Side effects:
  160.  *    The nameOpen routine is called on the prefix handle.  This ups
  161.  *    reference counts.
  162.  *
  163.  *----------------------------------------------------------------------
  164.  */
  165. /*ARGSUSED*/
  166. ReturnStatus
  167. Fsrmt_RpcPrefix(srvToken, clientID, command, storagePtr)
  168.     ClientData          srvToken;    /* Handle on server process passed to
  169.                      * Rpc_Reply */
  170.     int          clientID;    /* Sprite ID of client host */
  171.     int          command;    /* IGNORED */
  172.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  173.                      * request buffers and also indicate 
  174.                      * the exact amount of data in the 
  175.                      * request buffers.  The reply fields 
  176.                      * are initialized to NIL for the
  177.                      * pointers and 0 for the lengths.  
  178.                      * This can be passed to Rpc_Reply */
  179. {
  180.     char                *lookupName;
  181.     Fsprefix                *prefixPtr;
  182.     Fs_HandleHeader            *hdrPtr;
  183.     Fs_FileID                rootID;
  184.     int                    domainType;
  185.     int                    serverID;
  186.     ReturnStatus            status;
  187.     FsPrefixReplyParam            *prefixReplyPtr;
  188.  
  189.     status = Fsprefix_Lookup((char *) storagePtr->requestDataPtr,
  190.         FSPREFIX_EXPORTED | FSPREFIX_EXACT, clientID, &hdrPtr,
  191.         &rootID, &lookupName, &serverID, &domainType, &prefixPtr);
  192.     if (status == SUCCESS) {
  193.     register Rpc_ReplyMem        *replyMemPtr;
  194.     ClientData            streamData;
  195.     int                dataSize;
  196.  
  197.     prefixReplyPtr = mnew(FsPrefixReplyParam);
  198.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_EXPORT])(hdrPtr,
  199.             clientID, &prefixReplyPtr->fileID, &dataSize, &streamData);
  200.     if (status == SUCCESS) {
  201.         if (dataSize > 0) {
  202.         bcopy((Address)streamData, (Address)&prefixReplyPtr->openData,
  203.             dataSize);
  204.         free((Address)streamData);
  205.         }
  206.         storagePtr->replyParamPtr = (Address) (prefixReplyPtr);
  207.         storagePtr->replyParamSize = sizeof(FsPrefixReplyParam);
  208.         storagePtr->replyDataPtr = (Address)NIL;
  209.         storagePtr->replyDataSize = 0;
  210.  
  211.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  212.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  213.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  214.         Rpc_Reply(srvToken, SUCCESS, storagePtr, Rpc_FreeMem,
  215.             (ClientData)replyMemPtr);
  216.         return(SUCCESS);
  217.     } else {
  218.         free((Address)prefixReplyPtr);
  219.         printf( "Fsrmt_RpcPrefix, export \"%s\" failed %x\n",
  220.             storagePtr->requestDataPtr, status);
  221.         Fsprefix_HandleClose(prefixPtr, FSPREFIX_ANY);
  222.     }
  223.     }
  224.     if (RPC_IS_BROADCAST(srvToken)) {
  225.     return(RPC_NO_REPLY);
  226.     } else {
  227.     return(RPC_FS_NO_PREFIX);
  228.     }
  229. }
  230.  
  231. /*
  232.  *----------------------------------------------------------------------
  233.  *
  234.  * FsrmtOpen --
  235.  *
  236.  *    Open a remote file.  This sets up and conducts an RPC_FS_OPEN
  237.  *    remote procedure call to open the remote file.  This is called
  238.  *    from Fsprefix_LookupOperation based on the prefix table.  FsrmtOpen
  239.  *    makes an RPC to FslclOpen on the remote machine, and returns
  240.  *    the streamData for use by the client-open routine.
  241.  *
  242.  * RPC: The input parameters are the Fs_OpenArgs defined in fsNameOps.h.
  243.  *    The input data is a relative name.  The return parameter is a file
  244.  *    type used by our caller to branch to the client-open routine.  The
  245.  *    return data area has two possible return values.  In the normal
  246.  *    case it is a lump of data used by the client-open routine to set
  247.  *    up the I/O handle. If the name lookup re-directs to a different
  248.  *    server then the returned data is the new pathname.
  249.  *
  250.  * Results:
  251.  *    SUCCESS, FS_REDIRECT, or some error code from the lookup on the server.
  252.  *    If FS_REDIRECT, then *newNameInfoPtr has prefix information.
  253.  *
  254.  * Side effects:
  255.  *    Allocates memory for the returned streamData or re-directed path.
  256.  *    An openCount is left up during the open as part of the open/re-open
  257.  *    synchronization.
  258.  *
  259.  *----------------------------------------------------------------------
  260.  */
  261.  
  262. ReturnStatus
  263. FsrmtOpen(prefixHandle, relativeName, argsPtr, resultsPtr, 
  264.          newNameInfoPtrPtr)
  265.     Fs_HandleHeader  *prefixHandle;    /* Token from the prefix table */
  266.     char       *relativeName;    /* The name of the file to open. */
  267.     Address       argsPtr;        /* Ref. to Fs_OpenArgs */
  268.     Address       resultsPtr;        /* Ref. to Fs_OpenResults */
  269.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if
  270.                          * the server leaves 
  271.                          * its domain during lookup. */
  272. {
  273.     ReturnStatus    status;
  274.     Fs_OpenResults    *openResultsPtr = (Fs_OpenResults *)resultsPtr;
  275.     Rpc_Storage        storage;    /* Specifies RPC parameters/results */
  276.     char        replyName[FS_MAX_PATH_NAME_LENGTH];     /* This
  277.                      * may get filled with a
  278.                      * redirected pathname */
  279.     FsrmtOpenResultsParam    openResultsParam;
  280.     /*
  281.      * Synchronize with the re-open phase of recovery.
  282.      * We don't want opens to race with the recovery actions.
  283.      */
  284.     status = Fsprefix_OpenCheck(prefixHandle);
  285.     if (status != SUCCESS) {
  286.     return(status);
  287.     }
  288.  
  289.     /*
  290.      * Set up for the RPC.
  291.      */
  292.     storage.requestParamPtr = (Address) argsPtr;
  293.     storage.requestParamSize = sizeof(Fs_OpenArgs);
  294.     storage.requestDataPtr = (Address) relativeName;
  295.     storage.requestDataSize = strlen(relativeName) + 1;
  296.     storage.replyParamPtr = (Address) &openResultsParam;
  297.     storage.replyParamSize = sizeof(FsrmtOpenResultsParam);
  298.     storage.replyDataPtr = (Address) replyName;
  299.     storage.replyDataSize = FS_MAX_PATH_NAME_LENGTH;
  300.  
  301.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_OPEN, &storage);
  302.     if (status == SUCCESS) {
  303.     /*
  304.      * Allocate space for the stream data returned by the server.
  305.      * We then copy the streamData from our stack buffer.
  306.      */
  307.     /* This assumes openResults.dataSize was filled in correctly. */
  308.     *openResultsPtr = openResultsParam.openResults;
  309.     if (openResultsPtr->dataSize == 0) {
  310.         openResultsPtr->streamData = (ClientData)NIL;
  311.     } else {
  312.         openResultsPtr->streamData =
  313.             (ClientData)malloc(openResultsPtr->dataSize);
  314.         bcopy((Address) &(openResultsParam.openData), (Address) openResultsPtr->streamData, openResultsPtr->dataSize);
  315.     }
  316.     } else if (status == FS_LOOKUP_REDIRECT) {
  317.     /*
  318.      * Allocate space for the re-directed pathname and
  319.      * copy over the structure that we have on our stack.  A large
  320.      * buffer is allocated because it is used as a work area in
  321.      * FsprefixLookupRedirect to create a new absolute pathname.
  322.      */
  323.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  324.     (*newNameInfoPtrPtr)->prefixLength = openResultsParam.prefixLength;
  325.     (void)strcpy((*newNameInfoPtrPtr)->fileName, replyName);
  326.     }
  327.     Fsprefix_OpenDone(prefixHandle);
  328.     return(status);
  329. }
  330.  
  331. /*
  332.  *----------------------------------------------------------------------
  333.  *
  334.  * Fsrmt_RpcOpen --
  335.  *
  336.  *      Service stub for the RPC_FS_OPEN call.  This unpackages parameters
  337.  *    and branches to the local open routine.
  338.  *
  339.  * Results:
  340.  *    If this procedure returns SUCCESS then a reply has been sent to
  341.  *    the client.  If the arguments are bad then an error is 
  342.  *    returned and the main level sends back an error reply.
  343.  *
  344.  * Side effects:
  345.  *    None here, see FslclOpen.
  346.  *    
  347.  *
  348.  *----------------------------------------------------------------------
  349.  */
  350. /*ARGSUSED*/
  351. ReturnStatus
  352. Fsrmt_RpcOpen(srvToken, clientID, command, storagePtr)
  353.     ClientData          srvToken;    /* Handle on server process passed to
  354.                      * Rpc_Reply */
  355.     int          clientID;    /* Sprite ID of client host */
  356.     int          command;    /* IGNORED */
  357.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  358.                      * request buffers and also indicate 
  359.                      * the exact amount of data in the 
  360.                      * request buffers.  The reply fields 
  361.                      * are initialized to NIL for the
  362.                       * pointers and 0 for the lengths.  
  363.                      * This can be passed to Rpc_Reply */
  364. {
  365.     ReturnStatus        status;
  366.     register Fs_OpenArgs        *openArgsPtr;        /* RPC parameters */
  367.     register Fs_OpenResults    *openResultsPtr;    /* RPC results */
  368.     Fs_HandleHeader        *prefixHandlePtr;    /* Handle for domain */
  369.     Fs_RedirectInfo        *newNameInfoPtr;    /* prefix info for
  370.                              * redirected lookups */
  371.     FsrmtOpenResultsParam        *openResultsParamPtr;    /* open results, etc. */
  372.     int                domainType;        /* Local or Pseudo */
  373.  
  374.  
  375.     if (Recov_GetClientState(clientID) & CLT_RECOV_IN_PROGRESS) {
  376.     Net_HostPrint(clientID, "Dropping regular open during recovery\n");
  377.     return(RPC_SERVICE_DISABLED);
  378.     }
  379.     openArgsPtr = (Fs_OpenArgs *) storagePtr->requestParamPtr;
  380.     /*
  381.      * Get a handle on the prefix.  We need to have it unlocked in case
  382.      * we do I/O on the directory.
  383.      */
  384.     prefixHandlePtr =
  385.     (*fsio_StreamOpTable[openArgsPtr->prefixID.type].clientVerify)
  386.         (&openArgsPtr->prefixID, clientID, &domainType);
  387.     if (prefixHandlePtr == (Fs_HandleHeader *)NIL) {
  388.     return(FS_STALE_HANDLE);
  389.     }
  390.     Fsutil_HandleUnlock(prefixHandlePtr);
  391.  
  392.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  393.     openResultsParamPtr = mnew(FsrmtOpenResultsParam);
  394.     openResultsPtr = &(openResultsParamPtr->openResults);
  395.     fs_Stats.srvName.numReadOpens++;
  396.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_OPEN])(prefixHandlePtr,
  397.         (char *)storagePtr->requestDataPtr, (Address)openArgsPtr,
  398.         (Address)openResultsPtr, &newNameInfoPtr);
  399.     Fsutil_HandleRelease(prefixHandlePtr, FALSE);
  400.     if (status == SUCCESS) {
  401.     /*
  402.      * The open worked.  We return the whole Fs_OpenResults structure
  403.      * in the RPC parameter area, but it contains a pointer to
  404.      * stream data and a dataSize. That stream data is returned also
  405.      * as a separate field in the RPC parameter area, so it must be copied.
  406.      */
  407.     storagePtr->replyParamPtr = (Address)openResultsParamPtr;
  408.     storagePtr->replyParamSize = sizeof(FsrmtOpenResultsParam);
  409.     /* copy openData */
  410.     if (openResultsPtr->dataSize != 0 &&
  411.         ((Address)openResultsPtr->streamData) != (Address)NIL) {
  412.         bcopy((Address)openResultsPtr->streamData, (Address)&openResultsParamPtr->openData, openResultsPtr->dataSize);
  413.         free((Address)openResultsPtr->streamData);
  414.         storagePtr->replyDataPtr = (Address)NIL;
  415.         storagePtr->replyDataSize = 0;
  416.     }
  417.     } else if (status == FS_LOOKUP_REDIRECT) {
  418.     /*
  419.      * The file is not found on this server.
  420.      */
  421.     storagePtr->replyParamPtr = (Address)openResultsParamPtr;
  422.     storagePtr->replyParamSize = sizeof(FsrmtOpenResultsParam);
  423.     openResultsParamPtr->prefixLength = newNameInfoPtr->prefixLength;
  424.     storagePtr->replyDataSize = strlen(newNameInfoPtr->fileName) + 1;
  425.     storagePtr->replyDataPtr = (Address)malloc(storagePtr->replyDataSize);
  426.     (void)strcpy(storagePtr->replyDataPtr, newNameInfoPtr->fileName);
  427.     free((Address)newNameInfoPtr);
  428.     }
  429.     if (status == SUCCESS || status == FS_LOOKUP_REDIRECT) {
  430.     Rpc_ReplyMem    *replyMemPtr;
  431.  
  432.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  433.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  434.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  435.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  436.         (ClientData)replyMemPtr);
  437.         return(SUCCESS);
  438.     } else {
  439.     free((Address)openResultsParamPtr);
  440.         return(status);
  441.     }
  442. }
  443.  
  444. /*
  445.  *----------------------------------------------------------------------
  446.  *
  447.  * FsrmtReopen --
  448.  *
  449.  *    Open a handle at its server.  This sets up and conducts an RPC_FS_REOPEN
  450.  *    remote procedure call to reopen the remote file handle.
  451.  *
  452.  * Results:
  453.  *    The return from the RPC.
  454.  *
  455.  * Side effects:
  456.  *    None.
  457.  *
  458.  *----------------------------------------------------------------------
  459.  */
  460.  
  461. ReturnStatus
  462. FsrmtReopen(hdrPtr, inSize, inData, outSizePtr, outData)
  463.     Fs_HandleHeader  *hdrPtr;        /* Handle to reopen */
  464.     int            inSize;        /* Size of input data */
  465.     Address        inData;        /* Input data to server's reopen proc */
  466.     int            *outSizePtr;    /* In/Out return data size */
  467.     Address        outData;    /* Return parameter block */
  468. {
  469.     register ReturnStatus    status;
  470.     Rpc_Storage        storage;    /* Specifies RPC parameters/results */
  471.  
  472.     storage.requestParamPtr = inData;
  473.     storage.requestParamSize = inSize;
  474.     storage.requestDataPtr = (Address) NIL;
  475.     storage.requestDataSize = 0;
  476.     storage.replyParamPtr = outData;
  477.     storage.replyParamSize = *outSizePtr;
  478.     storage.replyDataPtr = (Address) NIL;
  479.     storage.replyDataSize = 0;
  480.  
  481.     status = Rpc_Call(hdrPtr->fileID.serverID, RPC_FS_REOPEN, &storage);
  482.     *outSizePtr = storage.replyParamSize;
  483.     return(status);
  484. }
  485.  
  486. /*
  487.  *----------------------------------------------------------------------
  488.  *
  489.  * Fsrmt_RpcReopen --
  490.  *
  491.  *    This is the service stub for RPC_FS_REOPEN.  This switches
  492.  *    out to a stream type reopen procedure.  To do this it must
  493.  *    assume that the first part of the parameter block contains
  494.  *    a fileID, the thing to be re-opened.
  495.  *
  496.  * Results:
  497.  *    If this procedure returns SUCCESS then a reply has been sent to
  498.  *    the client.  If the arguments are bad then an error is 
  499.  *    returned and the main level sends back an error reply.
  500.  *
  501.  * Side effects:
  502.  *    None.
  503.  *    
  504.  *
  505.  *----------------------------------------------------------------------
  506.  */
  507. /*ARGSUSED*/
  508. ReturnStatus
  509. Fsrmt_RpcReopen(srvToken, clientID, command, storagePtr)
  510.     ClientData          srvToken;    /* Handle on server process passed to
  511.                       * Rpc_Reply */
  512.     int          clientID;    /* Sprite ID of client host */
  513.     int          command;    /* IGNORED */
  514.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  515.                      * request buffers and also indicate 
  516.                      * the exact amount of data in the 
  517.                      * request buffers.  The reply fields 
  518.                      * are initialized to NIL for the
  519.                       * pointers and 0 for the lengths.  
  520.                      * This can be passed to Rpc_Reply */
  521. {
  522.     register Fs_FileID *fileIDPtr;
  523.     register ReturnStatus status;
  524.  
  525.     extern int fsutil_NumRecovering; /* XXX put in fsutil.h */
  526.  
  527.     if (storagePtr->requestParamSize <= 0) {
  528.     /*
  529.      * Check to make sure our parameter size is big enough to be
  530.      * a proper reopen request.  (As of 1/91, we've been suffering
  531.      * from a 0 paramSize bug in reopen requests.)
  532.      */
  533.     Net_HostPrint(clientID, "Zero-length parameters to reopen request!\n");
  534.     return FAILURE;
  535.     }
  536.     if ((Recov_GetClientState(clientID) & CLT_RECOV_IN_PROGRESS) == 0) {
  537.     Recov_SetClientState(clientID, CLT_RECOV_IN_PROGRESS);
  538.     fsutil_NumRecovering++;
  539.     if (fsutil_NumRecovering == 1) {
  540.         /*
  541.          * The print statements are tweaked so that the first client
  542.          * to recover triggers this message, and the last
  543.          * client to end recovery triggers another message.
  544.          * See fsRecovery.c for the complementary printf.
  545.          */
  546.         Net_HostPrint(clientID, "initiating recovery\n");
  547.     }
  548.     }
  549.  
  550.     fileIDPtr = (Fs_FileID *)storagePtr->requestParamPtr;
  551.     if (fileIDPtr->serverID != rpc_SpriteID) {
  552.     /*
  553.      * Filesystem version mis-match.
  554.      */
  555.     return(GEN_INVALID_ARG);
  556.     }
  557.     fileIDPtr->type = Fsio_MapRmtToLclType(fileIDPtr->type);
  558.     if (fileIDPtr->type < 0) {
  559.     return(GEN_INVALID_ARG);
  560.     }
  561.     status = (*fsio_StreamOpTable[fileIDPtr->type].reopen)((Fs_HandleHeader *)NIL,
  562.         clientID, (ClientData) storagePtr->requestParamPtr,
  563.         &storagePtr->replyParamSize,
  564.         (ClientData *)&storagePtr->replyParamPtr);
  565.  
  566.     Recov_AddHandleCountToClientState(fileIDPtr->type, clientID, status);
  567.  
  568.     if (status == SUCCESS) {
  569.     Rpc_ReplyMem    *replyMemPtr;
  570.  
  571.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  572.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  573.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  574.         Rpc_Reply(srvToken, SUCCESS, storagePtr, Rpc_FreeMem,
  575.         (ClientData)replyMemPtr);
  576.     }
  577.     return(status);
  578. }
  579.  
  580. /*
  581.  *----------------------------------------------------------------------
  582.  *
  583.  * FsrmtBulkReopen --
  584.  *
  585.  *    Open a set of handles at the server.  This sets up and conducts an
  586.  *    RPC_FS_BULK_REOPEN
  587.  *    remote procedure call to reopen the remote file handles.
  588.  *
  589.  * Results:
  590.  *    The return from the RPC.
  591.  *
  592.  * Side effects:
  593.  *    None.
  594.  *
  595.  *----------------------------------------------------------------------
  596.  */
  597.  
  598. ReturnStatus
  599. FsrmtBulkReopen(serverID, inSize, inData, outSizePtr, outData)
  600.     int            serverID;    /* Server to do reopens. */
  601.     int            inSize;        /* Size of input data */
  602.     Address        inData;        /* Input data to server's reopen proc */
  603.     int            *outSizePtr;    /* In/Out return data size */
  604.     Address        outData;    /* Return parameter block */
  605. {
  606.     register ReturnStatus    status;
  607.     Rpc_Storage        storage;    /* Specifies RPC parameters/results */
  608.     Fmt_Format        sendFormat = mach_Format;
  609.     Fmt_Format        returnFormat;
  610.     int            fmtStatus;
  611.  
  612.     storage.requestParamPtr = (Address) &sendFormat;
  613.     storage.requestParamSize = sizeof (mach_Format);
  614.     storage.requestDataPtr = inData;
  615.     storage.requestDataSize = inSize;
  616.     storage.replyParamPtr = (Address) &returnFormat;
  617.     storage.replyParamSize = sizeof (Fmt_Format);;
  618.     storage.replyDataPtr = (Address) malloc(*outSizePtr);
  619.     storage.replyDataSize = *outSizePtr;
  620.  
  621.     status = Rpc_Call(serverID, RPC_FS_BULK_REOPEN, &storage);
  622.     if (storage.replyDataSize > *outSizePtr) {
  623.     panic("FsrmtBulkReopen: size of return data is too large.");
  624.     }
  625.     if (status == SUCCESS) {
  626.     if (mach_Format != returnFormat) {
  627.         int        outSize;
  628.  
  629.         inSize = storage.replyDataSize;
  630.         if (Fmt_Size("w*", returnFormat, &inSize, mach_Format,
  631.             &outSize) != 0 || outSize > storage.replyDataSize) {
  632.         /*
  633.          * Different alignment on two machines.  This isn't
  634.          * set up to deal with this, since I'm assuming that
  635.          * all the stuff here is int's and won't have different
  636.          * alignnment properties.
  637.          */
  638.         printf("FsrmtBulkReopen: bad alignment on two machines.");
  639.         free((char *) storage.replyDataPtr);
  640.         return GEN_INVALID_ARG;
  641.         }
  642.         inSize = storage.replyDataSize;
  643.         fmtStatus = Fmt_Convert("w*", returnFormat, &inSize,
  644.             storage.replyDataPtr, mach_Format, &outSize, outData);
  645.         if (fmtStatus != 0) {
  646.         printf("Format of bulk reopen failed <0x%x>\n", fmtStatus);
  647.         free((char *) storage.replyDataPtr);
  648.         return GEN_INVALID_ARG;
  649.         }
  650.         *outSizePtr = outSize;
  651.     } else {
  652.         *outSizePtr = storage.replyDataSize;
  653.         bcopy(storage.replyDataPtr, outData, *outSizePtr);
  654.     }
  655.     }
  656.         
  657.     free((char *) storage.replyDataPtr);
  658.     return(status);
  659. }
  660.  
  661. /*
  662.  *----------------------------------------------------------------------
  663.  *
  664.  * Fsrmt_RpcBulkReopen --
  665.  *
  666.  *    This is the service stub for RPC_FS_BULK_REOPEN.  This switches
  667.  *    out to stream type reopen procedures.
  668.  *
  669.  * Results:
  670.  *    If this procedure returns SUCCESS then a reply has been sent to
  671.  *    the client.  If the arguments are bad then an error is 
  672.  *    returned and the main level sends back an error reply.
  673.  *
  674.  * Side effects:
  675.  *    None.
  676.  *    
  677.  *
  678.  *----------------------------------------------------------------------
  679.  */
  680. /*ARGSUSED*/
  681. ReturnStatus
  682. Fsrmt_RpcBulkReopen(srvToken, clientID, command, storagePtr)
  683.     ClientData          srvToken;    /* Handle on server process passed to
  684.                       * Rpc_Reply */
  685.     int          clientID;    /* Sprite ID of client host */
  686.     int          command;    /* IGNORED */
  687.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  688.                      * request buffers and also indicate 
  689.                      * the exact amount of data in the 
  690.                      * request buffers.  The reply fields 
  691.                      * are initialized to NIL for the
  692.                       * pointers and 0 for the lengths.  
  693.                      * This can be passed to Rpc_Reply */
  694. {
  695.     ReturnStatus    status;
  696.     Fsutil_BulkHandle        *bulkHandleSpace;
  697.     int                numBulkHandles;
  698.     Fsutil_BulkReturn        *bulkReturnSpace;
  699.     int                i;
  700.     Address            newStatePtr;
  701.     int                newSize;
  702.     Fmt_Format            inFormat;
  703.     Rpc_ReplyMem        *replyMemPtr;
  704.     int                fmtStatus;
  705.  
  706.     extern int fsutil_NumRecovering; /* XXX put in fsutil.h */
  707.  
  708.     if (storagePtr->requestParamSize != sizeof (Fmt_Format)) {
  709.     /*
  710.      * Check to make sure our parameter size is correct for
  711.      * a proper reopen request.
  712.      */
  713.     Net_HostPrint(clientID, "Bad length params to bulk reopen request!\n");
  714.     return FAILURE;
  715.     }
  716.     if (storagePtr->requestDataSize <= 0) {
  717.     Net_HostPrint(clientID, "Zero-length data to bulk reopen request!\n");
  718.     return FAILURE;
  719.     }
  720.     if ((Recov_GetClientState(clientID) & CLT_RECOV_IN_PROGRESS) == 0) {
  721.     Recov_SetClientState(clientID, CLT_RECOV_IN_PROGRESS);
  722.     fsutil_NumRecovering++;
  723.     if (fsutil_NumRecovering == 1) {
  724.         /*
  725.          * The print statements are tweaked so that the first client
  726.          * to recover triggers this message, and the last
  727.          * client to end recovery triggers another message.
  728.          * See fsRecovery.c for the complementary printf.
  729.          */
  730.         Net_HostPrint(clientID, "initiating recovery\n");
  731.     }
  732.     }
  733.     inFormat = *((Fmt_Format *) (storagePtr->requestParamPtr));
  734.     if (inFormat != mach_Format) {
  735.     int    inSize;
  736.     int    outSize;
  737.  
  738.     inSize = storagePtr->requestDataSize;
  739.     if (Fmt_Size("w*", inFormat, &inSize, mach_Format, &outSize) != 0 ||
  740.         outSize > storagePtr->requestDataSize) {
  741.         /*
  742.          * Different alignment on two machines.  This isn't
  743.          * set up to deal with this, since I'm assuming that
  744.          * all the stuff here is int's and won't have different
  745.          * alignnment properties.
  746.          */
  747.         printf("Fsrmt_RpcBulkReopen: bad alignment on two machines.");
  748.         return GEN_INVALID_ARG;
  749.     }
  750.  
  751.     inSize = storagePtr->requestDataSize;
  752.     bulkHandleSpace = (Fsutil_BulkHandle *) malloc(outSize);
  753.     fmtStatus = Fmt_Convert("w*", inFormat, &inSize,
  754.         (Address) storagePtr->requestDataPtr, mach_Format, &outSize,
  755.         (Address) bulkHandleSpace);
  756.     if (fmtStatus != 0) {
  757.         printf("Format of bulk reopen failed <0x%x>\n", fmtStatus);
  758.         free((char *) bulkHandleSpace);
  759.         return GEN_INVALID_ARG;
  760.     }
  761.     storagePtr->requestDataSize = outSize;
  762.     } else {
  763.     bulkHandleSpace = (Fsutil_BulkHandle *) (storagePtr->requestDataPtr);
  764.     }
  765.     numBulkHandles = storagePtr->requestDataSize / sizeof (Fsutil_BulkHandle);
  766.     storagePtr->replyDataPtr =
  767.         (Address) malloc(numBulkHandles * sizeof (Fsutil_BulkReturn));
  768.     bulkReturnSpace = (Fsutil_BulkReturn *) (storagePtr->replyDataPtr);
  769.     storagePtr->replyDataSize = numBulkHandles * sizeof (Fsutil_BulkReturn);
  770.  
  771.     for (i = 0; i < numBulkHandles; i++) {
  772.     newStatePtr = (Address) NIL;
  773.     newSize = 0;
  774.     if (bulkHandleSpace[i].serverID != rpc_SpriteID) {
  775.         /*
  776.          * Filesystem version mis-match.
  777.          */
  778.         bulkReturnSpace[i].status = GEN_INVALID_ARG;
  779.         continue;
  780.     }
  781.     bulkHandleSpace[i].type = Fsio_MapRmtToLclType(bulkHandleSpace[i].type);
  782.     if (bulkHandleSpace[i].type < 0) {
  783.         bulkReturnSpace[i].status = GEN_INVALID_ARG;
  784.         continue;
  785.     }
  786.     status = (*fsio_StreamOpTable[bulkHandleSpace[i].type].reopen)
  787.         ((Fs_HandleHeader *)NIL,
  788.         clientID, (ClientData) (bulkHandleSpace[i].reopenParams),
  789.         &newSize, (ClientData *) &newStatePtr);
  790.     if (newSize != 0) {
  791.         bcopy((Address) newStatePtr, (Address) bulkReturnSpace[i].state,
  792.             newSize);
  793.         free((Address) newStatePtr);
  794.     }
  795.  
  796.     Recov_AddHandleCountToClientState(bulkHandleSpace[i].type, clientID,
  797.         status);
  798.     bulkReturnSpace[i].status = status;
  799.     }
  800.  
  801.     if (inFormat != mach_Format) {
  802.     free((char *) bulkHandleSpace);
  803.     }
  804.     storagePtr->replyParamPtr = (Address) malloc(sizeof (Fmt_Format));
  805.     *((Fmt_Format *) storagePtr->replyParamPtr) = mach_Format;
  806.     storagePtr->replyParamSize = sizeof (Fmt_Format);
  807.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  808.     replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  809.     replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  810.     Rpc_Reply(srvToken, SUCCESS, storagePtr, Rpc_FreeMem,
  811.         (ClientData) replyMemPtr);
  812.  
  813.     return SUCCESS;
  814. }
  815.  
  816. /*
  817.  *----------------------------------------------------------------------
  818.  *
  819.  * Fsrmt_ServerReopen --
  820.  *
  821.  *    Tell client to begin recovery with server.
  822.  *
  823.  * Results:
  824.  *    The return from the RPC.
  825.  *
  826.  * Side effects:
  827.  *    May determine that client is running an old kernel.
  828.  *
  829.  *----------------------------------------------------------------------
  830.  */
  831. ReturnStatus
  832. Fsrmt_ServerReopen(clientID)
  833.     int            clientID;    /* Client to start reopens. */
  834. {
  835.     ReturnStatus    status;
  836.     Rpc_Storage        storage;    /* Specifies RPC parameters/results */
  837.  
  838.     storage.requestParamPtr = (Address) NIL;
  839.     storage.requestParamSize = 0;
  840.     storage.requestDataPtr = (Address) NIL;
  841.     storage.requestDataSize = 0;
  842.     storage.replyParamPtr = (Address) NIL;
  843.     storage.replyParamSize = 0;
  844.     storage.replyDataPtr = (Address) NIL;
  845.     storage.replyDataSize = 0;
  846.  
  847.     status = Rpc_Call(clientID, RPC_FS_SERVER_REOPEN, &storage);
  848.  
  849.     return status;
  850. }
  851.  
  852. /*
  853.  *----------------------------------------------------------------------
  854.  *
  855.  * Fsrmt_RpcServerReopen --
  856.  *
  857.  *    This is the service stub for RPC_FS_SERVER_REOPEN.  This
  858.  *    is executed by clients to begin their recovery with the server.
  859.  *
  860.  * Results:
  861.  *    Status for RPC (success always, I think?).
  862.  *
  863.  * Side effects:
  864.  *    Start recovery stuff.
  865.  *    
  866.  *
  867.  *----------------------------------------------------------------------
  868.  */
  869. /*ARGSUSED*/
  870. ReturnStatus
  871. Fsrmt_RpcServerReopen(srvToken, serverID, command, storagePtr)
  872.     ClientData          srvToken;    /* Handle on server process passed to
  873.                       * Rpc_Reply */
  874.     int          serverID;    /* Sprite ID of server calling us */
  875.     int          command;    /* IGNORED */
  876.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  877.                      * request buffers and also indicate 
  878.                      * the exact amount of data in the 
  879.                      * request buffers.  The reply fields 
  880.                      * are initialized to NIL for the
  881.                       * pointers and 0 for the lengths.  
  882.                      * This can be passed to Rpc_Reply */
  883. {
  884.     /*
  885.      * Start recovery things in motion on client.
  886.      */
  887.     if (recov_ClientIgnoreServerDriven) {
  888.     return RPC_INVALID_RPC;
  889.     }
  890.     Recov_StartServerDrivenRecovery(serverID);
  891.     Rpc_Reply(srvToken, SUCCESS, storagePtr, (int (*)())NIL, (ClientData)NIL);
  892.  
  893.     return SUCCESS;
  894. }
  895.  
  896. /*
  897.  * Union of things passed as close data.  Right now, it only seems to
  898.  * be cached attributes.
  899.  */
  900. typedef union FsCloseData {
  901.     Fscache_Attributes    attrs;
  902. } FsCloseData;
  903.  
  904.  
  905. /*
  906.  * Request params for the close RPC.  The data for the close is put in the
  907.  * closeData field so that it too can be byte-swapped. The field is for stream
  908.  * specific data that gets pushed back to the server when the client closes.
  909.  * Currently, it seems only to be Fscache_Attributes.
  910.  * 
  911.  */
  912.  
  913.  
  914. typedef struct FsRemoteCloseParams {
  915.     Fs_FileID    fileID;        /* File to close */
  916.     Fs_FileID    streamID;    /* Stream to close */
  917.     Proc_PID    procID;        /* Process doing the close */
  918.     int        flags;        /* Flags from the stream */
  919.     FsCloseData    closeData;    /* Seems to be only Fscache_Attributes... */
  920.     int        closeDataSize;    /* actual size of info in closeData field. */
  921. } FsRemoteCloseParams;
  922.  
  923. /*
  924.  *----------------------------------------------------------------------
  925.  *
  926.  * Fsrmt_Close --
  927.  *
  928.  *    Tell the server that we have closed one reference to its file.  This
  929.  *    is used by the remote file and remote device close routines.  This
  930.  *    routine uses RPC_FS_CLOSE to invoke the correct stream-type close
  931.  *    routine on the I/O server.
  932.  *
  933.  * Results:
  934.  *    SUCCESS.
  935.  *
  936.  * Side effects:
  937.  *    This marks the handle as needing recovery if the RPC fails due
  938.  *    to communication problems.
  939.  *
  940.  *----------------------------------------------------------------------
  941.  */
  942. /*ARGSUSED*/
  943. ReturnStatus
  944. Fsrmt_Close(streamPtr, clientID, procID, flags, dataSize, closeData)
  945.     Fs_Stream        *streamPtr;    /* Stream to close.  This is needed
  946.                      * (instead of I/O handle) so the
  947.                      * server can close its shadow stream */
  948.     int            clientID;    /* IGNORED, implicitly passed by RPC */
  949.     Proc_PID        procID;        /* Process ID of closer */
  950.     int            flags;        /* Flags from the stream being closed */
  951.     int            dataSize;    /* Size of *closeData, or Zero */
  952.     ClientData        closeData;    /* Copy of cached I/O attributes.
  953.                         * Sometimes NIL!  */
  954. {
  955.     Fsrmt_IOHandle    *rmtHandlePtr;    /* Handle to close */
  956.     Rpc_Storage     storage;
  957.     ReturnStatus     status;
  958.  
  959.     FsRemoteCloseParams    params;
  960.     rmtHandlePtr = (Fsrmt_IOHandle *)streamPtr->ioHandlePtr;
  961.     params.fileID = rmtHandlePtr->hdr.fileID;
  962.     params.streamID = streamPtr->hdr.fileID;
  963.     params.procID = procID;
  964.     params.flags = flags;
  965.     if (closeData != (ClientData) NIL) {
  966.     params.closeData = *((FsCloseData *)closeData);
  967.     params.closeDataSize = dataSize;
  968.     } else {
  969.     params.closeDataSize = 0;
  970.     }
  971.     storage.requestParamPtr = (Address)¶ms;
  972.     storage.requestParamSize = sizeof(params);
  973.     storage.requestDataPtr = (Address)NIL;
  974.     storage.requestDataSize = 0;
  975.     storage.replyParamPtr = (Address)NIL;
  976.     storage.replyParamSize = 0;
  977.     storage.replyDataPtr = (Address)NIL;
  978.     storage.replyDataSize = 0;
  979.  
  980.     status = Rpc_Call(rmtHandlePtr->hdr.fileID.serverID, RPC_FS_CLOSE,&storage);
  981.  
  982.     if (status == RPC_TIMEOUT || status == FS_STALE_HANDLE ||
  983.     status == RPC_SERVICE_DISABLED) {
  984.     /*
  985.      * Mark the handle as needing recovery if we can't tell the server
  986.      * about this close.
  987.      */
  988.     Fsutil_WantRecovery((Fs_HandleHeader *)rmtHandlePtr);
  989.     }
  990.     return(status);
  991. }
  992.  
  993. /*
  994.  *----------------------------------------------------------------------
  995.  *
  996.  * Fsrmt_RpcClose --
  997.  *
  998.  *    Server stub for RPC_FS_CLOSE.  This verifies the client and branches
  999.  *    to the stream-type close routine.
  1000.  *
  1001.  * Results:
  1002.  *    STALE_HANDLE if the handle is out-of-date. FS_FILE_REMOVED is returned
  1003.  *    if the file has been removed.  SUCCESS in the normal case, or
  1004.  *    an error code from the stream-type close routine.
  1005.  *
  1006.  * Side effects:
  1007.  *    None here, see the stream-type close routines.
  1008.  *
  1009.  *----------------------------------------------------------------------
  1010.  */
  1011. /*ARGSUSED*/
  1012. ReturnStatus
  1013. Fsrmt_RpcClose(srvToken, clientID, command, storagePtr)
  1014.     ClientData          srvToken;    /* Handle on server process passed to
  1015.                       * Rpc_Reply */
  1016.     int          clientID;    /* Sprite ID of client host */
  1017.     int          command;    /* IGNORED */
  1018.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  1019.                      * request buffers and also indicate 
  1020.                      * the exact amount of data in the 
  1021.                      * request buffers.  The reply fields 
  1022.                      * are initialized to NIL for the
  1023.                       * pointers and 0 for the lengths.  
  1024.                      * This can be passed to Rpc_Reply */
  1025. {
  1026.     register    FsRemoteCloseParams    *paramsPtr;
  1027.     register    Fs_Stream        *streamPtr;
  1028.     register    Fs_HandleHeader        *hdrPtr;
  1029.     ReturnStatus            status;
  1030.     Fs_Stream                dummy;
  1031.     register ClientData clientData;
  1032.  
  1033.     if (storagePtr->requestParamSize < sizeof(FsRemoteCloseParams)) {
  1034.     printf("Fsrmt_RpcClose: rpc from host %d had undersize param (%d)\n",
  1035.         clientID, storagePtr->requestParamSize);
  1036.     status = GEN_INVALID_ARG;
  1037.     goto exit;
  1038.     }
  1039.     paramsPtr = (FsRemoteCloseParams *) storagePtr->requestParamPtr;
  1040.  
  1041.     hdrPtr = (*fsio_StreamOpTable[paramsPtr->fileID.type].clientVerify)
  1042.         (¶msPtr->fileID, clientID, (int *)NIL);
  1043.     if (hdrPtr == (Fs_HandleHeader *) NIL) {
  1044.     status = FS_STALE_HANDLE;
  1045.     goto exit;
  1046.     }
  1047.     if (paramsPtr->streamID.type == -1) {
  1048.     /*
  1049.      * This is a close of a prefix handle which doesn't have a stream.
  1050.      */
  1051.     bzero((Address)&dummy, sizeof(Fs_Stream));
  1052.     streamPtr = &dummy;
  1053.     streamPtr->ioHandlePtr = hdrPtr;
  1054.     } else {
  1055.     streamPtr = Fsio_StreamClientVerify(¶msPtr->streamID, hdrPtr,
  1056.             clientID);
  1057.     if (streamPtr == (Fs_Stream *)NIL) {
  1058.         printf("Fsrmt_RpcClose no stream <%d> to handle <%d,%d> client %d\n",
  1059.             paramsPtr->streamID.minor,
  1060.             paramsPtr->fileID.major, paramsPtr->fileID.minor,
  1061.             clientID);
  1062.         Fsutil_HandleRelease(hdrPtr, TRUE);
  1063.         status = (paramsPtr->streamID.minor < 0) ? GEN_INVALID_ARG
  1064.                              : FS_STALE_HANDLE ;
  1065.         goto exit;
  1066.     }
  1067.     }
  1068.  
  1069.     /*
  1070.      * Call the file type close routine to release the I/O handle
  1071.      * and clean up.  This call unlocks and decrements the reference
  1072.      * count on the handle.
  1073.      */
  1074.     if (paramsPtr->closeDataSize != 0) {
  1075.     clientData = (ClientData)¶msPtr->closeData;
  1076.     } else {
  1077.     clientData = (ClientData)NIL;
  1078.     }
  1079.     status = (*fsio_StreamOpTable[hdrPtr->fileID.type].close)
  1080.         (streamPtr, clientID, paramsPtr->procID,
  1081.         paramsPtr->flags, paramsPtr->closeDataSize, clientData);
  1082. #ifdef lint
  1083.     status = Fsio_FileClose(streamPtr, clientID, paramsPtr->procID,
  1084.         paramsPtr->flags, paramsPtr->closeDataSize, clientData);
  1085.     status = Fsio_PipeClose(streamPtr, clientID, paramsPtr->procID,
  1086.         paramsPtr->flags, paramsPtr->closeDataSize, clientData);
  1087.     status = Fsio_DeviceClose(streamPtr, clientID, paramsPtr->procID,
  1088.         paramsPtr->flags, paramsPtr->closeDataSize, clientData);
  1089.     status = FspdevPseudoStreamClose(streamPtr, clientID, paramsPtr->procID,
  1090.         paramsPtr->flags, paramsPtr->closeDataSize, clientData);
  1091. #endif /* lint */
  1092.     if (streamPtr != &dummy) {
  1093.     /*
  1094.      * Take the client of the stream's list and nuke the server's
  1095.      * shadow stream if there are no client's left.
  1096.      */
  1097.     if (Fsio_StreamClientClose(&streamPtr->clientList, clientID)) {
  1098.         Fsio_StreamDestroy(streamPtr);
  1099.     } else {
  1100.         Fsutil_HandleRelease(streamPtr, TRUE);
  1101.     }
  1102.     }
  1103. exit:
  1104.     /* XXX
  1105.      * For transparent recovery, maybe we should do something here to make
  1106.      * sure server and client agree on state?
  1107.      */
  1108.     /*
  1109.      * Send back the reply.
  1110.      */
  1111.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL, (ClientData)NIL);
  1112.  
  1113.     return(SUCCESS);    /* So Rpc_Server doesn't return a reply msg */
  1114. }
  1115.  
  1116. /*
  1117.  *----------------------------------------------------------------------
  1118.  *
  1119.  * FsrmtRemove --
  1120.  *
  1121.  *    This uses the RPC_FS_UNLINK call to invoke FslclRemove
  1122.  *    on the file server.
  1123.  *
  1124.  * Results:
  1125.  *    None.
  1126.  *
  1127.  * Side effects:
  1128.  *    Does the remove.
  1129.  *
  1130.  *----------------------------------------------------------------------
  1131.  */
  1132. /*ARGSUSED*/
  1133. ReturnStatus
  1134. FsrmtRemove(prefixHandle, relativeName, argsPtr, resultsPtr, 
  1135.            newNameInfoPtrPtr)
  1136.     Fs_HandleHeader   *prefixHandle;    /* Handle from the prefix table */
  1137.     char        *relativeName;    /* The name of the file to remove */
  1138.     Address        argsPtr;        /* Ref to Fs_LookupArgs */
  1139.     Address        resultsPtr;        /* == NIL */
  1140.     Fs_RedirectInfo **newNameInfoPtrPtr; /* We return this if the server leaves 
  1141.                        its domain during the lookup. */
  1142. {
  1143.     ReturnStatus    status;
  1144.     Rpc_Storage        storage;
  1145.     Fs_RedirectInfo    redirectInfo;
  1146.     int            prefixLength;
  1147.  
  1148.     storage.requestParamPtr = (Address) argsPtr;
  1149.     storage.requestParamSize = sizeof(Fs_LookupArgs);
  1150.     storage.requestDataPtr = (Address) relativeName;
  1151.     storage.requestDataSize = strlen(relativeName) + 1;
  1152.     storage.replyParamPtr = (Address) &prefixLength;
  1153.     storage.replyParamSize = sizeof (int);
  1154.     storage.replyDataPtr = (Address)&redirectInfo;
  1155.     storage.replyDataSize = sizeof(Fs_RedirectInfo);
  1156.  
  1157.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_UNLINK, &storage);
  1158.     if (status == FS_LOOKUP_REDIRECT) {
  1159.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  1160.     (*newNameInfoPtrPtr)->prefixLength = prefixLength;
  1161.     (void)strcpy((*newNameInfoPtrPtr)->fileName, redirectInfo.fileName);
  1162.     }
  1163.     return(status);
  1164. }
  1165.  
  1166. /*
  1167.  *----------------------------------------------------------------------
  1168.  *
  1169.  * FsrmtRemoveDir --
  1170.  *
  1171.  *    Remove a directory.  This uses the RPC_FS_RMDIR call to invoke
  1172.  *    FslclRemoveDir on the file server.
  1173.  *
  1174.  * Results:
  1175.  *    None.
  1176.  *
  1177.  * Side effects:
  1178.  *    Does the remove.
  1179.  *
  1180.  *----------------------------------------------------------------------
  1181.  */
  1182. /*ARGSUSED*/
  1183. ReturnStatus
  1184. FsrmtRemoveDir(prefixHandle, relativeName, argsPtr, resultsPtr, 
  1185.            newNameInfoPtrPtr)
  1186.     Fs_HandleHeader   *prefixHandle;    /* Handle from the prefix table */
  1187.     char        *relativeName;    /* The name of the file to remove */
  1188.     Address        argsPtr;        /* Ref to Fs_LookupArgs */
  1189.     Address        resultsPtr;        /* == NIL */
  1190.     Fs_RedirectInfo **newNameInfoPtrPtr; /* We return this if the server leaves 
  1191.                        its domain during the lookup. */
  1192. {
  1193.     ReturnStatus    status;
  1194.     Rpc_Storage        storage;
  1195.     Fs_RedirectInfo    redirectInfo;
  1196.     int            prefixLength;
  1197.  
  1198.     storage.requestParamPtr = (Address) argsPtr;
  1199.     storage.requestParamSize = sizeof(Fs_LookupArgs);
  1200.     storage.requestDataPtr = (Address) relativeName;
  1201.     storage.requestDataSize = strlen(relativeName) + 1;
  1202.     storage.replyParamPtr = (Address) &prefixLength;
  1203.     storage.replyParamSize = sizeof (int);
  1204.     storage.replyDataPtr = (Address)&redirectInfo;
  1205.     storage.replyDataSize = sizeof(Fs_RedirectInfo);
  1206.  
  1207.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_RMDIR, &storage);
  1208.     if (status == FS_LOOKUP_REDIRECT) {
  1209.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  1210.     (*newNameInfoPtrPtr)->prefixLength = prefixLength;
  1211.     (void)strcpy((*newNameInfoPtrPtr)->fileName, redirectInfo.fileName);
  1212.     }
  1213.     return(status);
  1214. }
  1215.  
  1216. /*
  1217.  *----------------------------------------------------------------------
  1218.  *
  1219.  * Fsrmt_RpcRemove --
  1220.  *
  1221.  *    The service stub for FS_RPC_UNLINK use to remove a file or directory.
  1222.  *
  1223.  * Results:
  1224.  *    If this procedure returns SUCCESS then a reply has been sent to
  1225.  *    the client.  If the arguments are bad then an error is 
  1226.  *    returned and the main level sends back an error reply.
  1227.  *
  1228.  * Side effects:
  1229.  *    None.
  1230.  *
  1231.  *----------------------------------------------------------------------
  1232.  */
  1233. /*ARGSUSED*/
  1234. ReturnStatus
  1235. Fsrmt_RpcRemove(srvToken, clientID, command, storagePtr)
  1236.     ClientData          srvToken;    /* Handle on server process passed to
  1237.                       * Rpc_Reply */
  1238.     int          clientID;    /* Sprite ID of client host */
  1239.     int          command;    /* RPC_FS_UNLINK, RPC_FS_RMDIR */
  1240.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  1241.                      * request buffers and also indicate 
  1242.                      * the exact amount of data in the 
  1243.                      * request buffers.  The reply fields 
  1244.                      * are initialized to NIL for the
  1245.                       * pointers and 0 for the lengths.  
  1246.                      * This can be passed to Rpc_Reply */
  1247. {
  1248.     ReturnStatus    status;
  1249.     Fs_HandleHeader    *prefixHandlePtr;
  1250.     Fs_RedirectInfo    *newNameInfoPtr;
  1251.     Fs_LookupArgs    *lookupArgsPtr;
  1252.     int            domainType;
  1253.  
  1254.     lookupArgsPtr = (Fs_LookupArgs *)storagePtr->requestParamPtr;
  1255.     prefixHandlePtr =
  1256.     (*fsio_StreamOpTable[lookupArgsPtr->prefixID.type].clientVerify)
  1257.         (&lookupArgsPtr->prefixID, clientID, &domainType);
  1258.     if (prefixHandlePtr == (Fs_HandleHeader *) NIL) {
  1259.     return(FS_STALE_HANDLE);
  1260.     } 
  1261.     Fsutil_HandleRelease(prefixHandlePtr, TRUE);
  1262.  
  1263.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  1264.     switch (command) {
  1265.     case RPC_FS_UNLINK:
  1266.         fs_Stats.srvName.removes++;
  1267.         command = FS_DOMAIN_REMOVE;
  1268.         break;
  1269.     case RPC_FS_RMDIR:
  1270.         fs_Stats.srvName.removeDirs++;
  1271.         command = FS_DOMAIN_REMOVE_DIR;
  1272.         break;
  1273.     default:
  1274.         return(GEN_INVALID_ARG);
  1275.     }
  1276.     status = (*fs_DomainLookup[domainType][command])(prefixHandlePtr,
  1277.             (char *) storagePtr->requestDataPtr,
  1278.             (Address) lookupArgsPtr, (Address) NIL, &newNameInfoPtr);
  1279.     if (status == FS_LOOKUP_REDIRECT) {
  1280.     Rpc_ReplyMem    *replyMemPtr;
  1281.  
  1282.     storagePtr->replyDataPtr = (Address) newNameInfoPtr;
  1283.     storagePtr->replyDataSize = sizeof(Fs_RedirectInfo);
  1284.     storagePtr->replyParamPtr = (Address) malloc(sizeof (int));
  1285.     storagePtr->replyParamSize = sizeof (int);
  1286.     *((int *) (storagePtr->replyParamPtr)) = newNameInfoPtr->prefixLength;
  1287.  
  1288.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1289.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  1290.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  1291.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  1292.         (ClientData)replyMemPtr);
  1293.     } else {
  1294.     Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL,
  1295.         (ClientData)NIL);
  1296.     }
  1297.  
  1298.     return(SUCCESS);
  1299. }
  1300.  
  1301.  
  1302. /*
  1303.  *----------------------------------------------------------------------
  1304.  *
  1305.  * FsrmtMakeDir --
  1306.  *
  1307.  *    Make the named directory.  This uses the RPC_FS_MAKE_DIR call
  1308.  *    to invoke FslclMakeDir on the file server.
  1309.  *
  1310.  * Results:
  1311.  *    A return code from the file server or the RPC.
  1312.  *
  1313.  * Side effects:
  1314.  *    Makes the directory.
  1315.  *
  1316.  *----------------------------------------------------------------------
  1317.  */
  1318. /*ARGSUSED*/
  1319. ReturnStatus
  1320. FsrmtMakeDir(prefixHandle, relativeName, argsPtr, resultsPtr, 
  1321.         newNameInfoPtrPtr)
  1322.     Fs_HandleHeader *prefixHandle;   /* Handle from the prefix table */
  1323.     char        *relativeName;   /* The name of the directory to create */
  1324.     Address        argsPtr;        /* Ref. to Fs_OpenArgs */
  1325.     Address        resultsPtr;        /* == NIL */
  1326.     Fs_RedirectInfo **newNameInfoPtrPtr;/* We return this if the server leaves 
  1327.                     * its domain during the lookup. */
  1328. {
  1329.     ReturnStatus    status;
  1330.     Rpc_Storage        storage;
  1331.     Fs_RedirectInfo    redirectInfo;
  1332.     int            prefixLength;
  1333.  
  1334.     storage.requestParamPtr = (Address) argsPtr;
  1335.     storage.requestParamSize = sizeof(Fs_OpenArgs);
  1336.     storage.requestDataPtr = (Address) relativeName;
  1337.     storage.requestDataSize = strlen(relativeName) + 1;
  1338.     storage.replyParamPtr = (Address) &prefixLength;
  1339.     storage.replyParamSize = sizeof (int);
  1340.     storage.replyDataPtr = (Address)&redirectInfo;
  1341.     storage.replyDataSize = sizeof(Fs_RedirectInfo);
  1342.  
  1343.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_MKDIR, &storage);
  1344.     if (status == FS_LOOKUP_REDIRECT) {
  1345.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  1346.     (*newNameInfoPtrPtr)->prefixLength = prefixLength;
  1347.     (void)strcpy((*newNameInfoPtrPtr)->fileName, redirectInfo.fileName);
  1348.     }
  1349.     return(status);
  1350. }
  1351.  
  1352. /*
  1353.  *----------------------------------------------------------------------
  1354.  *
  1355.  * Fsrmt_RpcMakeDir --
  1356.  *
  1357.  *    Handle a make directory request from a client.
  1358.  *
  1359.  * Results:
  1360.  *    If this procedure returns SUCCESS then a reply has been sent to
  1361.  *    the client.  If the arguments are bad then an error is 
  1362.  *    returned and the main level sends back an error reply.
  1363.  *
  1364.  * Side effects:
  1365.  *    None.
  1366.  *
  1367.  *----------------------------------------------------------------------
  1368.  */
  1369.  
  1370. /*ARGSUSED*/
  1371. ReturnStatus
  1372. Fsrmt_RpcMakeDir(srvToken, clientID, command, storagePtr)
  1373.     ClientData          srvToken;    /* Handle on server process passed to
  1374.                       * Rpc_Reply */
  1375.     int          clientID;    /* Sprite ID of client host */
  1376.     int          command;    /* Command identifier */
  1377.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  1378.                      * request buffers and also indicate 
  1379.                      * the exact amount of data in the 
  1380.                      * request buffers.  The reply fields 
  1381.                      * are initialized to NIL for the
  1382.                       * pointers and 0 for the lengths.  
  1383.                      * This can be passed to Rpc_Reply */
  1384. {
  1385.     ReturnStatus    status;
  1386.     Fs_HandleHeader    *prefixHandlePtr;
  1387.     Fs_RedirectInfo    *newNameInfoPtr;
  1388.     Fs_OpenArgs        *openArgsPtr;
  1389.     int            domainType;
  1390.  
  1391.     openArgsPtr = (Fs_OpenArgs *) storagePtr->requestParamPtr;
  1392.     if (openArgsPtr->prefixID.serverID != rpc_SpriteID) {
  1393.     return(GEN_INVALID_ARG);
  1394.     }
  1395.  
  1396.     prefixHandlePtr =
  1397.     (*fsio_StreamOpTable[openArgsPtr->prefixID.type].clientVerify)
  1398.         (&openArgsPtr->prefixID, clientID, &domainType);
  1399.     if (prefixHandlePtr == (Fs_HandleHeader *) NIL) {
  1400.     return(FS_STALE_HANDLE);
  1401.     }
  1402.     Fsutil_HandleRelease(prefixHandlePtr, TRUE);
  1403.  
  1404.     fs_Stats.srvName.makeDirs++;
  1405.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  1406.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_MAKE_DIR])(prefixHandlePtr,
  1407.         (char *)storagePtr->requestDataPtr,
  1408.         (Address) openArgsPtr, (Address) NIL, &newNameInfoPtr);
  1409.     if (status == FS_LOOKUP_REDIRECT) {
  1410.     Rpc_ReplyMem    *replyMemPtr;
  1411.  
  1412.     storagePtr->replyDataPtr = (Address)newNameInfoPtr;
  1413.     storagePtr->replyDataSize = sizeof(Fs_RedirectInfo);
  1414.     storagePtr->replyParamPtr = (Address) malloc(sizeof (int));
  1415.     storagePtr->replyParamSize = sizeof (int);
  1416.     *((int *)(storagePtr->replyParamPtr)) = newNameInfoPtr->prefixLength;
  1417.  
  1418.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1419.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  1420.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  1421.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  1422.         (ClientData)replyMemPtr);
  1423.     } else {
  1424.         Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL,
  1425.         (ClientData)NIL);
  1426.     }
  1427.  
  1428.     return(SUCCESS);
  1429. }
  1430.  
  1431.  
  1432. /*
  1433.  *----------------------------------------------------------------------
  1434.  *
  1435.  * FsrmtMakeDevice --
  1436.  *
  1437.  *    Create a device file.  This uses the RPC_FS_MAKE_DEV call to create
  1438.  *    the special file on the file server.
  1439.  *
  1440.  * Results:
  1441.  *    None.
  1442.  *
  1443.  * Side effects:
  1444.  *    Makes a device file.
  1445.  *
  1446.  *----------------------------------------------------------------------
  1447.  */
  1448. /*ARGSUSED*/
  1449. ReturnStatus
  1450. FsrmtMakeDevice(prefixHandle, relativeName, argsPtr, resultsPtr,
  1451.                    newNameInfoPtrPtr)
  1452.     Fs_HandleHeader *prefixHandle;   /* Handle from the prefix table */
  1453.     char           *relativeName;   /* The name of the file. */
  1454.     Address        argsPtr;        /* Ref. to FsMakeDevArgs */
  1455.     Address        resultsPtr;        /* == NIL */
  1456.     Fs_RedirectInfo **newNameInfoPtrPtr;/* We return this if the server leaves 
  1457.                     * its domain during the lookup. */
  1458. {
  1459.     ReturnStatus    status;
  1460.     Rpc_Storage        storage;
  1461.     Fs_RedirectInfo    redirectInfo;
  1462.     int            prefixLength;
  1463.  
  1464.     storage.requestParamPtr = (Address) argsPtr;
  1465.     storage.requestParamSize = sizeof(Fs_MakeDeviceArgs);
  1466.     storage.requestDataPtr = (Address) relativeName;
  1467.     storage.requestDataSize = strlen(relativeName) + 1;
  1468.     storage.replyParamPtr = (Address) &prefixLength;
  1469.     storage.replyParamSize = sizeof (int);
  1470.     storage.replyDataPtr = (Address)&redirectInfo;
  1471.     storage.replyDataSize = sizeof(Fs_RedirectInfo);
  1472.  
  1473.     status = Rpc_Call(prefixHandle->fileID.serverID, RPC_FS_MKDEV, &storage);
  1474.     if (status == FS_LOOKUP_REDIRECT) {
  1475.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  1476.     (*newNameInfoPtrPtr)->prefixLength = prefixLength;
  1477.     (void)strcpy((*newNameInfoPtrPtr)->fileName, redirectInfo.fileName);
  1478.     }
  1479.     return(status);
  1480. }
  1481.  
  1482. /*
  1483.  *----------------------------------------------------------------------
  1484.  *
  1485.  * Fsrmt_RpcMakeDev --
  1486.  *
  1487.  *    Service stub for RPC_FS_MKDEV.  This calls FslclMakeDevice.
  1488.  *
  1489.  * Results:
  1490.  *    If this procedure returns SUCCESS then a reply has been sent to
  1491.  *    the client.  If the arguments are bad then an error is 
  1492.  *    returned and the main level sends back an error reply.
  1493.  *
  1494.  * Side effects:
  1495.  *    None.
  1496.  *
  1497.  *----------------------------------------------------------------------
  1498.  */
  1499.  
  1500. /*ARGSUSED*/
  1501. ReturnStatus
  1502. Fsrmt_RpcMakeDev(srvToken, clientID, command, storagePtr)
  1503.     ClientData          srvToken;    /* Handle on server process passed to
  1504.                       * Rpc_Reply */
  1505.     int          clientID;    /* Sprite ID of client host */
  1506.     int          command;    /* Command identifier */
  1507.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  1508.                      * request buffers and also indicate 
  1509.                      * the exact amount of data in the 
  1510.                      * request buffers.  The reply fields 
  1511.                      * are initialized to NIL for the
  1512.                       * pointers and 0 for the lengths.  
  1513.                      * This can be passed to Rpc_Reply */
  1514. {
  1515.     ReturnStatus    status;
  1516.     Fs_MakeDeviceArgs    *makeDevArgsPtr;
  1517.     Fs_HandleHeader    *prefixHandlePtr;
  1518.     Fs_RedirectInfo    *newNameInfoPtr;
  1519.     int            domainType;
  1520.  
  1521.     makeDevArgsPtr = (Fs_MakeDeviceArgs *) storagePtr->requestParamPtr;
  1522.     prefixHandlePtr = 
  1523.     (*fsio_StreamOpTable[makeDevArgsPtr->open.prefixID.type].clientVerify)
  1524.         (&makeDevArgsPtr->open.prefixID, clientID, &domainType);
  1525.     if (prefixHandlePtr == (Fs_HandleHeader *) NIL) {
  1526.     return(FS_STALE_HANDLE);
  1527.     }
  1528.     Fsutil_HandleRelease(prefixHandlePtr, TRUE);
  1529.  
  1530.     fs_Stats.srvName.makeDevices++;
  1531.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  1532.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_MAKE_DEVICE])(prefixHandlePtr,
  1533.         (char *)storagePtr->requestDataPtr, (Address) makeDevArgsPtr,
  1534.         (Address) NIL, &newNameInfoPtr);
  1535.     if (status == FS_LOOKUP_REDIRECT) {
  1536.     Rpc_ReplyMem    *replyMemPtr;
  1537.  
  1538.     storagePtr->replyDataPtr = (Address)newNameInfoPtr;
  1539.     storagePtr->replyDataSize = sizeof(Fs_RedirectInfo);
  1540.     storagePtr->replyParamPtr = (Address) malloc(sizeof (int));
  1541.     storagePtr->replyParamSize = sizeof (int);
  1542.     *((int *) (storagePtr->replyParamPtr)) = newNameInfoPtr->prefixLength;
  1543.  
  1544.         replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1545.         replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  1546.         replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  1547.         Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  1548.             (ClientData)replyMemPtr);
  1549.     } else {
  1550.         Rpc_Reply(srvToken, status, storagePtr, (int (*)())NIL,
  1551.             (ClientData)NIL);
  1552.     }
  1553.     return(SUCCESS);
  1554. }
  1555.  
  1556. /*
  1557.  *----------------------------------------------------------------------
  1558.  *
  1559.  * TwoNameOperation --
  1560.  *
  1561.  *    Common stub for renaming a file or making a hard link.
  1562.  *
  1563.  * Results:
  1564.  *    A return status.
  1565.  *
  1566.  * Side effects:
  1567.  *    None.
  1568.  *
  1569.  *----------------------------------------------------------------------
  1570.  */
  1571. static ReturnStatus
  1572. TwoNameOperation(command, prefixHandle1, relativeName1, prefixHandle2, 
  1573.      relativeName2, lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1574.     int            command;        /* Which Rpc: Mv or Ln */
  1575.     Fs_HandleHeader     *prefixHandle1;        /* Handle from prefix table */
  1576.     char         *relativeName1;        /* The new name of the file. */
  1577.     Fs_HandleHeader     *prefixHandle2;        /* Handle from prefix table */
  1578.     char         *relativeName2;        /* The new name of the file. */
  1579.     Fs_LookupArgs    *lookupArgsPtr;        /* Contains IDs */
  1580.     Fs_RedirectInfo    **newNameInfoPtrPtr;    /* We return this if the server
  1581.                          * leaves its domain during the
  1582.                          * lookup. */
  1583.     Boolean         *name1ErrorPtr;        /* If we return REDIRECT or
  1584.                          * STALE_HANDLE this indicates
  1585.                          * if that applies to the first
  1586.                          * pathname or the second */
  1587. {
  1588.     Fs_2PathParams    params;
  1589.     Fs_2PathData        *requestDataPtr;    /* too big for stack */
  1590.     Fs_2PathReply    replyParams;
  1591.     Rpc_Storage        storage;
  1592.     ReturnStatus    status;
  1593.     Fs_RedirectInfo    redirectInfo;
  1594.  
  1595.     requestDataPtr = mnew(Fs_2PathData);
  1596.  
  1597.     params.lookup = *lookupArgsPtr;
  1598.     params.lookup.prefixID = prefixHandle1->fileID;
  1599.     params.prefixID2 = prefixHandle2->fileID;
  1600.  
  1601.     (void)strcpy(requestDataPtr->path1, relativeName1);
  1602.     (void)strcpy(requestDataPtr->path2, relativeName2);
  1603.  
  1604.     storage.requestParamPtr = (Address) ¶ms;
  1605.     storage.requestParamSize = sizeof (Fs_2PathParams);
  1606.     storage.requestDataPtr = (Address) requestDataPtr;
  1607.     storage.requestDataSize = sizeof (Fs_2PathData);
  1608.  
  1609.     storage.replyParamPtr = (Address) &replyParams;
  1610.     storage.replyParamSize = sizeof (Fs_2PathReply);
  1611.     storage.replyDataPtr = (Address)&redirectInfo;
  1612.     storage.replyDataSize = sizeof(Fs_RedirectInfo);
  1613.  
  1614.     status = Rpc_Call(prefixHandle1->fileID.serverID, command, &storage);
  1615.     *name1ErrorPtr = replyParams.name1ErrorP;
  1616.     if (status == FS_LOOKUP_REDIRECT) {
  1617.     *newNameInfoPtrPtr = mnew(Fs_RedirectInfo);
  1618.     (*newNameInfoPtrPtr)->prefixLength = replyParams.prefixLength;
  1619.     (void)strcpy((*newNameInfoPtrPtr)->fileName, redirectInfo.fileName);
  1620.     }
  1621.     free((Address)requestDataPtr);
  1622.  
  1623.     return(status);
  1624. }
  1625.  
  1626. /*
  1627.  *----------------------------------------------------------------------
  1628.  *
  1629.  * Fsrmt_Rpc2Path --
  1630.  *
  1631.  *    Common service stub for FsrmtRename and FsrmtHardLink.
  1632.  *
  1633.  * Results:
  1634.  *    If this procedure returns SUCCESS then a reply has been sent to
  1635.  *    the client.  If the arguments are bad then FS_STALE_HANDLE is 
  1636.  *    returned and the main level sends back an error reply.
  1637.  *
  1638.  * Side effects:
  1639.  *    Calls the local rename or hard link routine to attempt the lock 
  1640.  *    operation.
  1641.  *
  1642.  *----------------------------------------------------------------------
  1643.  */
  1644. ReturnStatus
  1645. Fsrmt_Rpc2Path(srvToken, clientID, command, storagePtr)
  1646.     ClientData srvToken;    /* Handle on server process passed to
  1647.                  * Rpc_Reply */
  1648.     int clientID;        /* Sprite ID of client host */
  1649.     int command;        /* Command identifier */
  1650.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  1651.                  * buffers and also indicate the exact amount
  1652.                  * of data in the request buffers.  The reply
  1653.                  * fields are initialized to NIL for the
  1654.                  * pointers and 0 for the lengths.  This can
  1655.                  * be passed to Rpc_Reply */
  1656. {
  1657.     register    Fs_2PathParams        *paramsPtr;
  1658.     register    Fs_LookupArgs        *lookupArgsPtr;
  1659.     register    Fs_HandleHeader        *prefixHandle1Ptr;
  1660.     register    Fs_HandleHeader        *prefixHandle2Ptr;
  1661.     register    Rpc_ReplyMem        *replyMemPtr;
  1662.     Fs_RedirectInfo            *newNameInfoPtr;
  1663.     Boolean                name1Error = FALSE;
  1664.     Fs_2PathReply            *replyParamsPtr;
  1665.     Fs_2PathData                *pathDataPtr;
  1666.     ReturnStatus            status = SUCCESS;
  1667.     int                    domainType;
  1668.  
  1669.     if (storagePtr->requestParamSize < sizeof(Fs_2PathParams)) {
  1670.     printf("Fsrmt_Rpc2Path: rpc from host %d had undersize param (%d)\n",
  1671.         clientID, storagePtr->requestParamSize);
  1672.     status = GEN_INVALID_ARG;
  1673.     goto exit;
  1674.     }
  1675.     if (storagePtr->requestDataSize < sizeof(Fs_2PathData)) {
  1676.     printf("Fsrmt_Rpc2Path: rpc from host %d had undersize data (%d)\n",
  1677.         clientID, storagePtr->requestDataSize);
  1678.     status = GEN_INVALID_ARG;
  1679.     goto exit;
  1680.     }
  1681.     paramsPtr = (Fs_2PathParams *)storagePtr->requestParamPtr;
  1682.     pathDataPtr = (Fs_2PathData *)storagePtr->requestDataPtr;
  1683.     lookupArgsPtr = ¶msPtr->lookup;
  1684.     prefixHandle1Ptr =
  1685.     (*fsio_StreamOpTable[lookupArgsPtr->prefixID.type].clientVerify)
  1686.         (&lookupArgsPtr->prefixID, clientID, &domainType);
  1687.  
  1688.     if (prefixHandle1Ptr == (Fs_HandleHeader *)NIL) {
  1689.     name1Error = TRUE;
  1690.     status = FS_STALE_HANDLE;
  1691.     goto exit;
  1692.     } else {
  1693.     Fsutil_HandleUnlock(prefixHandle1Ptr);
  1694.     }
  1695.     if (paramsPtr->prefixID2.serverID != rpc_SpriteID) {
  1696.     /*
  1697.      * Second pathname doesn't even start with us.  However, we are
  1698.      * called in case the first pathname redirects away from us.
  1699.      */
  1700.     prefixHandle2Ptr = (Fs_HandleHeader *)NIL;
  1701.     } else {
  1702.     prefixHandle2Ptr =
  1703.         (*fsio_StreamOpTable[paramsPtr->prefixID2.type].clientVerify)
  1704.         (¶msPtr->prefixID2, clientID, (int *)NIL);
  1705.     if (prefixHandle2Ptr == (Fs_HandleHeader *)NIL) {
  1706.         Fsutil_HandleRelease(prefixHandle1Ptr, FALSE);
  1707.         name1Error = FALSE;
  1708.         status = FS_STALE_HANDLE;
  1709.         goto exit;
  1710.     } else {
  1711.         Fsutil_HandleUnlock(prefixHandle2Ptr);
  1712.     }
  1713.     }
  1714.  
  1715.     newNameInfoPtr = (Fs_RedirectInfo *) NIL;
  1716.     if (command == RPC_FS_RENAME) {
  1717.     fs_Stats.srvName.renames++;
  1718.     command = FS_DOMAIN_RENAME;
  1719.     } else if (command == RPC_FS_LINK) {
  1720.     fs_Stats.srvName.hardLinks++;
  1721.     command = FS_DOMAIN_HARD_LINK;
  1722.     } else {
  1723.     printf( "Fsrmt_Rpc2Path: Bad command %d\n", command);
  1724.     status = FS_INVALID_ARG;
  1725.     }
  1726.     if (status == SUCCESS) {
  1727.     status = (*fs_DomainLookup[domainType][command])(prefixHandle1Ptr,
  1728.             pathDataPtr->path1, prefixHandle2Ptr, pathDataPtr->path2,
  1729.             lookupArgsPtr, &newNameInfoPtr, &name1Error);
  1730.     }
  1731.     Fsutil_HandleRelease(prefixHandle1Ptr, FALSE);
  1732.     if (prefixHandle2Ptr != (Fs_HandleHeader *)NIL) {
  1733.     Fsutil_HandleRelease(prefixHandle2Ptr, FALSE);
  1734.     }
  1735. exit:
  1736.     replyParamsPtr = (Fs_2PathReply *) malloc(sizeof (Fs_2PathReply));
  1737.     replyParamsPtr->name1ErrorP = name1Error;
  1738.     storagePtr->replyParamPtr = (Address) replyParamsPtr;
  1739.     storagePtr->replyParamSize = sizeof (Fs_2PathReply);
  1740.     if (status == FS_LOOKUP_REDIRECT) {
  1741.     replyParamsPtr->prefixLength = newNameInfoPtr->prefixLength;
  1742.     storagePtr->replyDataPtr = (Address) newNameInfoPtr;
  1743.     storagePtr->replyDataSize = sizeof(int) +
  1744.                 strlen(newNameInfoPtr->fileName) + 1;
  1745.     } else {
  1746.     replyParamsPtr->prefixLength = 0;
  1747.     /*
  1748.      * Reply data ptr already set to NIL
  1749.      */
  1750.      }
  1751.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1752.     replyMemPtr->paramPtr = (Address) replyParamsPtr;
  1753.     replyMemPtr->dataPtr = (Address) storagePtr->replyDataPtr;
  1754.     Rpc_Reply(srvToken, status, storagePtr, 
  1755.           (int (*)()) Rpc_FreeMem, (ClientData) replyMemPtr);
  1756.  
  1757.     return(SUCCESS);
  1758. }
  1759.  
  1760.  
  1761. /*
  1762.  *----------------------------------------------------------------------
  1763.  *
  1764.  * FsrmtRename --
  1765.  *
  1766.  *    Stub for renaming a file.
  1767.  *
  1768.  * Results:
  1769.  *    A return status.
  1770.  *
  1771.  * Side effects:
  1772.  *    None.
  1773.  *
  1774.  *----------------------------------------------------------------------
  1775.  */
  1776. ReturnStatus
  1777. FsrmtRename(prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  1778.     lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1779.     Fs_HandleHeader *prefixHandle1;    /* Handle from the prefix table */
  1780.     char *relativeName1;        /* The new name of the file. */
  1781.     Fs_HandleHeader *prefixHandle2;    /* Token from the prefix table */
  1782.     char *relativeName2;        /* The new name of the file. */
  1783.     Fs_LookupArgs *lookupArgsPtr;    /* Contains IDs */
  1784.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  1785.                      * its domain during the lookup. */
  1786.     Boolean *name1ErrorPtr;    /* TRUE if redirect info or other error
  1787.                  * condition if for the first pathname,
  1788.                  * FALSE means error is on second pathname. */
  1789. {
  1790.     return(TwoNameOperation(RPC_FS_RENAME, prefixHandle1, relativeName1, 
  1791.                      prefixHandle2, relativeName2, lookupArgsPtr, 
  1792.                 newNameInfoPtrPtr, name1ErrorPtr));
  1793. }
  1794.  
  1795.  
  1796. /*
  1797.  *----------------------------------------------------------------------
  1798.  *
  1799.  * FsrmtHardLink --
  1800.  *
  1801.  *    Stub for making a hard link between two files.
  1802.  *
  1803.  * Results:
  1804.  *    A return status.
  1805.  *
  1806.  * Side effects:
  1807.  *    None.
  1808.  *
  1809.  *----------------------------------------------------------------------
  1810.  */
  1811. ReturnStatus
  1812. FsrmtHardLink(prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  1813.         lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1814.     Fs_HandleHeader *prefixHandle1;    /* Token from the prefix table */
  1815.     char *relativeName1;        /* The new name of the file. */
  1816.     Fs_HandleHeader *prefixHandle2;    /* Token from the prefix table */
  1817.     char *relativeName2;        /* The new name of the file. */
  1818.     Fs_LookupArgs *lookupArgsPtr;    /* Contains IDs */
  1819.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server 
  1820.                      * leaves its domain during the lookup*/
  1821.     Boolean *name1ErrorPtr;    /* TRUE if redirect info or other error is
  1822.                  * for first path, FALSE if for the second. */
  1823. {
  1824.     return(TwoNameOperation(RPC_FS_LINK, prefixHandle1, relativeName1, 
  1825.                      prefixHandle2, relativeName2, lookupArgsPtr, 
  1826.                 newNameInfoPtrPtr, name1ErrorPtr));
  1827. }
  1828.